import { VxeUI } from 'vxe-pc-ui';
import { ElTreeSelect, ElTag } from 'element-plus';

/**
 * 获取属性值的通用函数
 * 优先从 sources 中获取属性值，如果不存在则返回 defaultValue。
 * @param {string} attrName - 属性名
 * @param {*} defaultValue - 默认值
 * @param {Object} sources - 属性来源对象数组，按优先级从高到低排列
 * @returns {*} 属性值
 */
const getAttributeValue = (attrName, defaultValue, ...sources) => {
  for (const source of sources) {
    if (source && source[attrName] !== undefined) {
      return source[attrName];
    }
  }
  return defaultValue;
};

/**
 * 获取嵌套属性值的通用函数
 * @param {Object} obj - 源对象
 * @param {string} path - 属性路径，例如 'user.name'
 * @returns {*} 属性值
 */
const getNestedPropertyValue = (obj, path) => {
  if (!obj || !path) return undefined;
  const parts = path.split('.');
  let current = obj;
  for (let i = 0; i < parts.length; i++) {
    if (current === null || typeof current !== 'object') {
      return undefined;
    }
    current = current[parts[i]];
  }
  return current;
};

/**
 * 在树形数据中查找节点
 * @param {Array} data - 树形数据
 * @param {*} value - 要查找的值
 * @param {string} valueKey - 值字段名，默认为 'value'
 * @param {string} childrenKey - 子节点字段名，默认为 'children'
 * @returns {Object|null} 找到的节点或null
 */
const findNodeInTree = (data, value, valueKey = 'value', childrenKey = 'children') => {
  if (!Array.isArray(data)) return null;
  
  for (const node of data) {
    if (node[valueKey] === value) {
      return node;
    }
    if (node[childrenKey] && Array.isArray(node[childrenKey])) {
      const found = findNodeInTree(node[childrenKey], value, valueKey, childrenKey);
      if (found) return found;
    }
  }
  return null;
};

/**
 * 获取节点的显示标签
 * @param {Object} node - 树节点
 * @param {string} labelKey - 标签字段名，默认为 'label'
 * @returns {string} 节点标签
 */
const getNodeLabel = (node, labelKey = 'label') => {
  return node ? (node[labelKey] || node.value || '') : '';
};

/**
 * 渲染 ElTreeSelect 的显示模式（非编辑状态）
 * @param {Object} renderOpts - 渲染选项，可以包含 props 和 attrs
 * @param {Object} params - 参数对象
 * @returns {JSX.Element} 渲染结果
 */
const renderTreeSelectDisplay = (renderOpts, params) => {
  // 确定有效的数据对象 (row for table, data for form - though display usually for table)
  const effectiveData = params?.row || params?.data || renderOpts.data || {};
  // 确定有效的列或项上下文
  const effectiveColumn = params?.column || {};
  const effectiveItem = params?.item || {};

  // 确定字段名
  const field =
    effectiveColumn.field || effectiveItem.field || renderOpts.field;

  if (!field) {
    console.warn('RaElTreeSelectRender: Missing field identifier in display mode');
    return <span>-</span>;
  }

  // 获取当前值，使用辅助函数支持多层属性访问
  const value = getNestedPropertyValue(effectiveData, field);

  // 获取树形数据
  const data = getAttributeValue(
    'data',
    [],
    renderOpts.props,
    renderOpts.attrs,
    renderOpts,
  );
  
  // 获取配置项
  const nodeKey = getAttributeValue(
    'nodeKey',
    'value',
    renderOpts.props,
    renderOpts.attrs,
    renderOpts,
  );
  
  const props = getAttributeValue(
    'props',
    { label: 'label', children: 'children', value: 'value' },
    renderOpts.props,
    renderOpts.attrs,
    renderOpts,
  );
  
  const multiple = getAttributeValue(
    'multiple',
    false,
    renderOpts.props,
    renderOpts.attrs,
    renderOpts,
  );

  // 如果值为空（null, undefined, 空字符串），则显示占位符
  if (value === null || value === undefined || value === '') {
    return <span>-</span>;
  }

  if (multiple) {
    // 处理多选情况，将值转换为数组
    const valueArray = Array.isArray(value) ? value : [value];
    const selectedTags = [];
    
    valueArray.forEach((val) => {
      const node = findNodeInTree(data, val, props.value || nodeKey, props.children);
      if (node) {
        // 渲染为 ElTag，并根据 node.tagType 设置 type 属性
        selectedTags.push(
          <ElTag
            key={node[props.value || nodeKey]}
            size="small"
            type={node.tagType || 'primary'} // 使用 node.tagType，如果不存在则为 primary
            style="margin-right: 4px;"
          >
            {getNodeLabel(node, props.label)}
          </ElTag>,
        );
      }
    });
    // 返回包含所有 ElTag 的片段
    return <>{selectedTags}</>;
  } else {
    // 处理单选情况
    const node = findNodeInTree(data, value, props.value || nodeKey, props.children);
    // 如果找到节点，则渲染为 ElTag，并根据 node.tagType 设置 type 属性，否则显示占位符
    return node ? (
      <ElTag
        size="small"
        type={node.tagType || 'primary'} // 使用 node.tagType，如果不存在则为 primary
      >
        {getNodeLabel(node, props.label)}
      </ElTag>
    ) : (
      <span>-</span>
    );
  }
};

/**
 * 渲染 ElTreeSelect 的编辑模式
 * @param {Object} renderOpts - 渲染选项，可以包含 props 和 attrs
 * @param {Object} params - 参数对象
 * @returns {JSX.Element} 渲染结果
 */
const renderTreeSelectEdit = (renderOpts, params) => {
  // 确定有效的数据对象 (row for table, data for form)
  const effectiveData = params?.row || params?.data || renderOpts.data || {};
  // 确定有效的列或项上下文
  const effectiveColumn = params?.column || {};
  const effectiveItem = params?.item || {};

  // 确定字段名
  const field =
    effectiveColumn.field || effectiveItem.field || renderOpts.field;

  if (!field) {
    console.error('RaElTreeSelectRender: Missing field identifier in edit mode');
    return null;
  }

  // 获取当前值，使用辅助函数支持多层属性访问
  const value = getNestedPropertyValue(effectiveData, field);

  // 获取树形数据
  const data = getAttributeValue(
    'data',
    [],
    renderOpts.props,
    renderOpts.attrs,
    renderOpts,
  );

  const elTreeSelectProps = renderOpts.props || {};
  const elTreeSelectAttrs = renderOpts.attrs || {};

  // 合并所有 ElTreeSelect 特定的 props 和 attrs
  const mergedElTreeSelectProps = {
    ...elTreeSelectAttrs, // 优先使用 attrs
    ...elTreeSelectProps, // 其次使用 props
    data: data, // 树形数据
    modelValue: value, // 绑定到当前单元格的值
    // 监听值变化，更新行数据
    onChange: (val) => {
      // 直接更新 effectiveData 对象
      // 假设 'field' 是一个直接属性，如果支持嵌套路径更新，需要更复杂的逻辑
      if (effectiveData) {
        effectiveData[field] = val;
      }
      // 如果需要触发 vxe-table 的内部状态更新或验证，可以取消注释下面这行
      // params.$table?.updateStatus(params); // 使用可选链操作符确保 $table 存在
    },
    // 默认属性，可以通过 renderOpts.props 或 renderOpts.attrs 覆盖
    placeholder: getAttributeValue(
      'placeholder',
      '请选择',
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    clearable: getAttributeValue(
      'clearable',
      true,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    filterable: getAttributeValue(
      'filterable',
      false,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    multiple: getAttributeValue(
      'multiple',
      false,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    disabled: getAttributeValue(
      'disabled',
      false,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    checkStrictly: getAttributeValue(
      'checkStrictly',
      false,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    checkOnClickNode: getAttributeValue(
      'checkOnClickNode',
      false,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    showCheckbox: getAttributeValue(
      'showCheckbox',
      false,
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    nodeKey: getAttributeValue(
      'nodeKey',
      'value',
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    props: getAttributeValue(
      'props',
      { label: 'label', children: 'children', value: 'value' },
      elTreeSelectProps,
      elTreeSelectAttrs,
      renderOpts,
    ),
    // 您可以在这里添加更多 ElTreeSelect 支持的属性
  };

  return <ElTreeSelect {...mergedElTreeSelectProps} />;
};

// 注册名为 'RaElTreeSelectRender' 的渲染器
VxeUI.renderer.add('RaElTreeSelectRender', {
  // 表格单元格编辑模式
  renderEdit(renderOpts, params) {
    return renderTreeSelectEdit(renderOpts, params);
  },

  // 表格单元格显示模式
  renderTableCell(renderOpts, params) {
    return renderTreeSelectDisplay(renderOpts, params);
  },

  // 表单项目渲染
  renderItemContent(renderOpts, params) {
    // 表单项通常需要编辑功能，所以也使用 renderTreeSelectEdit
    return renderTreeSelectEdit(renderOpts, params);
  },

  // 默认显示模式（与renderTableCell相同）
  renderDefault(renderOpts, params) {
    return renderTreeSelectDisplay(renderOpts, params);
  },
});

export default 'RaElTreeSelectRender';

